package com.uniovi.nmapgui;



import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;


import com.baomidou.mybatisplus.core.conditions.query.Query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uniovi.nmapgui.nmap.controller.CommandnestedController;
import com.uniovi.nmapgui.nmap.entity.Commandnested;
import com.uniovi.nmapgui.nmap.entity.Task;
import com.uniovi.nmapgui.nmap.entity.TaskIp;
import com.uniovi.nmapgui.nmap.mapper.CommandnestedMapper;
import com.uniovi.nmapgui.nmap.service.ICommandnestedService;
import com.uniovi.nmapgui.nmap.service.ITaskIpService;
import com.uniovi.nmapgui.nmap.service.ITaskService;
import com.uniovi.nmapgui.quartz.StartOfDayJob;
import com.uniovi.nmapgui.quartz.service.JobService;
import com.uniovi.nmapgui.util.R;
import org.joda.time.DateTime;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.uniovi.nmapgui.executor.CommandExecutor;
import com.uniovi.nmapgui.executor.CommandExecutorImpl;
import com.uniovi.nmapgui.executor.CommandExecutorObserver;
import com.uniovi.nmapgui.model.Command;
import com.uniovi.nmapgui.util.Filefinder;

@Controller
public class WebController implements CommandExecutorObserver{
	private List<Command> ongoingCommands  = new ArrayList<Command>();
	private List<Command> finishedCommands = new ArrayList<Command>();
	private Command command;
	private boolean finishedCommandQueued=true;
	private InitialConfigurator config = new InitialConfigurator();

	//用来保存每个任务的  副表属性
	private Task task = new Task();

	@Resource
	CommandnestedMapper commandnestedMapper;
	@Autowired
	ICommandnestedService iCommandnestedServiceImpl;
	@Autowired
	ITaskIpService taskIpServiceImpl;
	@Autowired
	ITaskService taskServiceImpl;
	@Value("${fileUrl}")
	String fileUrl;

	@PostConstruct
	public void init(){
		config.configure();
	}
	
    @GetMapping("/nmap")
    public String command(Model model) {

    	command = new Command();
    	model.addAttribute("command", command);
    	model.addAttribute("scriptCategories", config.getScriptCategories());
    	model.addAttribute("menu", config.getMenu());
    	model.addAttribute("commands", ongoingCommands);
    	model.addAttribute("commands", finishedCommands);
    	finishedCommandQueued=true;
        return "index";
    }
    
    @GetMapping("/nmap-exe")
    public String command(Model model, @RequestParam String code) {
    	command =  new Command(code);
    	ongoingCommands.add(0,command);
    	executeCommand(command,"","");
    	model.addAttribute("command", command);
    	model.addAttribute("commands", ongoingCommands);
    	
        return "fragments/contents :: ongoing";
    }
    
    @GetMapping("/nmap/removeCommand")
    public String removeCommand(Model model, @RequestParam int index) {
    	finishedCommands.remove(index);
    	model.addAttribute("command", command);
    	model.addAttribute("finishedCommands", finishedCommands);
        return "fragments/contents :: finished";
    }
    
    
    @GetMapping("/nmap/update")
    public String updateOut(Model model) {  
    	
    	model.addAttribute("command", command);
    	model.addAttribute("commands", ongoingCommands);
    	return "fragments/contents :: ongoing";
    }
    
    @GetMapping("/nmap/update-finished")
    public String updateEnded(Model model) {

		//将nmap原生封装信息保留
		//iCommandnestedServiceImpl.saveToMysql(finishedCommands);
		task.setStatus(0);
		iCommandnestedServiceImpl.saveToMysqlNew(command,task);
		List<Command> finishedCommands = iCommandnestedServiceImpl.changeCommandnestTOCommand(iCommandnestedServiceImpl.list());
		for(int i = 0 ; i < finishedCommands.size() ; i++){
			model.addAttribute("command", command);
		}
		model.addAttribute("finishedCommands", finishedCommands);
		finishedCommandQueued=false;

    	return "fragments/contents :: finished";
    }

    @GetMapping("/nmap/finishedQueued")
    public @ResponseBody Boolean updateEnd() {
    	return finishedCommandQueued;
    }
    @GetMapping("/nmap/stopUpdating")
    public @ResponseBody Boolean stopUpdating() {
    	return ongoingCommands.isEmpty();
    }
    
    @GetMapping("/nmap/download/{filename}")
    public ResponseEntity<InputStreamResource> download(@PathVariable("filename") String filename) {
    	
    	InputStream file;
		try {
			file = new Filefinder().find(filename);
			InputStreamResource resource = new InputStreamResource(file);

	        return ResponseEntity.ok()
	                .contentType(MediaType.parseMediaType("application/octect-stream"))
	                .body(resource);
		} catch (FileNotFoundException e) {
			return ResponseEntity.notFound().build();
		}
    }

    //新接口  统一加入new 标识
	//新接口  添加
	@GetMapping("/newNmap-exe")
	@ResponseBody
	public R newNmapexe(@RequestParam String code,String summary) {
		command =  new Command(code);
		ongoingCommands.add(0,command);
		executeCommand(command,summary,code);
		return R.ok();
	}

	//运行完之后 将运行状态保存
	@GetMapping("/nmap/taskFinished")
	@ResponseBody
	public  R taskFinished() {

		task.setStatus(0);
		iCommandnestedServiceImpl.saveToMysqlNew(command,task);
		finishedCommandQueued=false;
		return R.ok();
	}

	//定时函数  每秒执行一次  验证 当前任务是否执行完毕
	//根据
	@Scheduled(cron="0/1 * *  * * ? ")   //每10秒执行一次
	public void aTask(){

		//选择在一个小时以内添加并且未完成的任务，
		DateTime now = new DateTime();
		now = now.plusHours(-1);
		QueryWrapper<Task> queryWrapper = new QueryWrapper();
		//System.out.println(now.plusHours(-1));
		//queryWrapper.between("starttime",now.plusHours(-1),now);
		queryWrapper.eq("status",1);
		queryWrapper.apply("UNIX_TIMESTAMP(starttime) >= UNIX_TIMESTAMP('" + now + "')");
		List<Task> tasks = taskServiceImpl.list(queryWrapper);
		//以taskid查看 commandnested表中
		for (int i = 0 ; i < tasks.size() ; i++){
			System.out.println(tasks.get(i).getCommand());
			QueryWrapper query = new QueryWrapper();
			query.eq("commandNestedId",tasks.get(i).getCommand());
			Commandnested commandnested = iCommandnestedServiceImpl.getOne(query);
			if (commandnested!=null){

				//说明巡查信息已经被存储  解析返回信息即可
				iCommandnestedServiceImpl.saveToMysql(commandnested,tasks.get(i));
			}
		}
	}


	@Override
    public void finishedCommand(Command cmd){
        ongoingCommands.remove(cmd);
        finishedCommands.add(0,cmd);
        finishedCommandQueued = true;
    }

    public void executeCommand(Command command,String summary,String code){
		//初始化 task
		task = new Task();
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		task.setStarttime(simpleDateFormat.format(new Date()));
		task.setFilename(fileUrl+"\\"+UUID.randomUUID().toString());
		task.setSummary(summary);
		task.setCode(code);
		task.setCommand(UUID.randomUUID().toString());
		//将task入库
		if (task!=null && taskServiceImpl.count(new QueryWrapper<>(task))==0){
			taskServiceImpl.save(task);
		}
    	CommandExecutor executor = new CommandExecutorImpl(command,task,commandnestedMapper);
    	executor.addObserver(this);
    	executor.execute();
    }

	public static void main(String[] args) {
		System.out.println(LocalDateTime.now());
	}
}
